﻿#include"stdafx.h"
#ifdef LK_FUNCTIONAL_
namespace LK
{
	namespace Functional
	{
		/**
		@brief 添加一个函数对象*/
		PDelegates& PDelegates::operator+=(PFunObjs const&d) { if (d!=null) { if (*this==null)return *this = d; *GetPtr() += d; }return*this; }
		/**
		@brief 移除一个函数对象*/
		PDelegates& PDelegates::operator-=(PFunObjs const&d) { if (d!=null && *this!=null)*GetPtr() -= d; return*this; }
		/**
		@brief 从函数对象构造*/
		PDelegates::PDelegates(PFunObjs const&f) :ptr<Object>(new IDelegates(f)) {}
		/**
		@brief 添加一个委托*/
		PDelegates& PDelegates::operator+=(PDelegates const&d) { if (d!=null) { if (*this==null)return *this = d; *GetPtr() += d; }return*this; }
		/**
		@brief 移除一个委托*/
		PDelegates& PDelegates::operator-=(PDelegates const&d) { if (d!=null &&*this!=null)*GetPtr() -= d; return*this; }
		/**
		@brief 获取函数对象数组的引用*/
		ptr<Collection::IArray<PFunObjs>>& PDelegates::GetFunObjsArrayRef()const { return Check()->funarr; }
		/**
		@brief 添加一个委托*/
		IDelegates& IDelegates::operator+=(PDelegates const&d)
		{
			if (d->funarr==null)return*this;
			if (funarr==null)funarr = d->funarr->Clone();
			else if (d.GetPtr() == this)
				funarr->AppendArray(d->funarr);
			else
			{
				//类型检查
				using namespace Collection;
				ptr<IArray<ptr<Type>>> check = funarr->FirstElement()->GetArgsType();
				ptr<IArray<ptr<Type>>> ch = d->funarr->FirstElement()->GetArgsType();
				if (check->size() != ch->size())Throw<PFunctionalException >(L"检测到+=的委托参数数量不一致：应传入" + ptr<String>(check->size() - 2) + L"个参数的委托，但传入的委托为 " + ptr<String>(ch->size() - 2) + L"个参数");
				if (check[0] != ch[0])Throw<PFunctionalException >(L"检测到+=的委托的返回值类型不一致：原委托返回类型是 " + check[0]->GetName() + L"，但传入委托的返回值类型是 " + ch[0]->GetName());
				for (index_t i = 2; i < check->size(); ++i)if (check[i] != ch[i])Throw<PFunctionalException >(L"检测到传入委托的第" + ptr<String>(i - 1) + L"个参数类型不一致：原委托参数类型是 " + check[i]->GetName() + L"，但传入的委托参数类型是 " + ch[i]->GetName());
				funarr->AppendArray(d->funarr);
			}
			return *this;
		}
		/**
		@brief 移除一个委托*/
		IDelegates& IDelegates::operator-=(PDelegates const&d)
		{
			if (d->funarr==null || funarr==null)return*this;
			if (d.GetPtr() == this)
				funarr = null;
			else
			{
				index_t i = 0;
				index_t len = d->funarr->size();
				while (i < len)
				{
					PFunObjs f = d->funarr[i];
					index_t j = 0;
					index_t tlen = funarr->size();
					PFunObjs* p = funarr;
					while (j < tlen&&!p[j]->Equals(f))++j;
					if (j < tlen) { funarr->RemoveAt(j); if (tlen == 1)break; }
					++i;
				}
			}
			return *this;
		}
		/**
		@brief 添加一个函数对象*/
		IDelegates& IDelegates::operator+=(PFunObjs const&d)
		{
			if (funarr==null)funarr = new LK::Collection::DefaultArray<PFunObjs>(1, d->Clone());
			else {
				//类型检查不通过
				using namespace Collection;
				ptr<IArray<ptr<Type>>> check = funarr->FirstElement()->GetArgsType();
				ptr<IArray<ptr<Type>>> ch = d->GetArgsType();
				if (check->size() != ch->size())Throw<PFunctionalException >(L"检测到+=的委托参数数量不一致：应传入" + ptr<String>(check->size() - 2) + L"个参数的委托，但传入的委托为 " + ptr<String>(ch->size() - 2) + L"个参数");
				if (check[0] != ch[0])Throw<PFunctionalException >(L"检测到+=的委托的返回值类型不一致：原委托返回类型是 " + check[0]->GetName() + L"，但传入委托的返回值类型是 " + ch[0]->GetName());
				for (index_t i = 2; i < check->size(); ++i)if (check[i] != ch[i])Throw<PFunctionalException >(L"检测到传入委托的第" + ptr<String>(i - 1) + L"个参数类型不一致：原委托参数类型是 " + check[i]->GetName() + L"，但传入的委托参数类型是 " + ch[i]->GetName());
				funarr->Append(d);
			}
			return *this;
		}
		/**
		@brief 移除一个函数对象*/
		IDelegates& IDelegates::operator-=(PFunObjs const&d)
		{
			if (funarr==null)return*this;
			PFunObjs*p = funarr;
			for (index_t i = 0; i < funarr->size(); ++i)
				if (p[i]->Equals(d)) { funarr->RemoveAt(i); break; }
			return *this;
		}
	}
}
#endif